package com.srx.openfeign.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.impl.DefaultClock;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;

import javax.crypto.SecretKey;
import java.util.Date;
import java.util.Map;

/**
 * Token工具类
 * <p>用于处理JWT（Json Web Token）的创建和解析操作。提供了生成符合HS256算法的密钥、创建JWT Token以及解析验证Token的方法。</p>
 * @author 沈汝旭
 * @since 2025-10-18 10:54:05
 * @version 1.0
 */
public class TokenUtil
{

    /**
     * 签名密钥
     */
    public static SecretKey key = Keys.hmacShaKeyFor(Decoders.BASE64.decode("thisismycode123456789thisismycode123456789thisismycode123456789thisismycode123456789thisismycode123456789"));



    /**
     * 创建Token
     *
     * @param subject 代表JWT的主体，通常包含用户标识
     * @param claims 自定义声明，包含额外的信息
     * @param issuer JWT的发行者信息
     * @param issuedAt JWT的发行时间
     * @param expiresAt JWT的过期时间
     * @return 生成的JWT字符串
     */
    public static String createToken(String subject, Map<String,Object> claims, String issuer, Date issuedAt, Date expiresAt)
    {
        return Jwts.builder()
                //设置JWT的主体部分，通常包含用户标识
                .subject(subject)
                //添加自定义声明
                .claims(claims)
                //生成的密钥对JWT进行签名
                .signWith(key)
                //设置JWT的发行者信息
                .issuer(issuer)
                //设置JWT的发行时间
                .issuedAt(issuedAt)
                //设置JWT的过期时间，这里设置为当前时间加1小时
                .expiration(expiresAt)
                //生成最终的JWT字符串
                .compact();
    }


    /**
     * 解析Token
     * <p>
     * 该方法主要用于验证和解析JWT（Json Web Token），以获取其中的claims（声明）
     * 如果token无效或解析过程中出现异常，方法将返回null
     *
     * @param token 待解析的JWT字符串
     * @return 解析成功的Jws<Claims>对象，包含JWT中的claims；如果解析失败或token无效，则返回null
     */
    public static Jws<Claims> parseToken(String token)
    {
	    // 检查token是否为空或为空字符串，如果是，则直接返回null
	    if (token == null || token.isEmpty())
	    {
		    return null;
	    }
	    try
	    {
		    // 使用Jwts.parser()创建一个JWT解析器，并配置解析所需的密钥和时钟
		    return Jwts.parser()
				    // 使用指定的密钥验证JWT的签名
				    .verifyWith(key)
				    // 设置10s偏差，以处理由于时间偏差导致的token提前失效问题
				    .clock(new DefaultClock()
				    {
					    @Override
					    public Date now()
					    {
						    // 当前时间减去10秒，以处理轻微的时间偏差
						    return new Date(System.currentTimeMillis() - 10 * 1000);
					    }
				    })
				    .build()
				    // 解析JWT并验证其签名，返回包含claims的Jws对象
				    .parseSignedClaims(token);
	    }
	    catch (Exception e)
	    {
		    // 如果解析过程中出现异常，返回null
		    return null;
	    }
    }


}
